/**
 * 创建构造函数
 * 定义原型（请求需求参数）
 * @param config
 * @constructor
 */
function Request(config = {}) {
	this.config = {};
	this.config.baseUrl = config.baseUrl ? config.baseUrl : '';
	this.config.dataType = config.dataType ? config.dataType : 'json';
	this.config.responseType = config.responseType ? config.responseType : 'text';
	this.config.header = config.header ? config.header : {};
	this.reqInterceptors = null;
	this.resInterceptors = null;
	this.interceptors = {
		request: fn => {
			this.reqInterceptors = fn;
		},
		response: fn => {
			this.resInterceptors = fn;
		}
	}
}

/**
 * 原型方法
 * create（创建）
 * request（拦截）
 * REQUESTMAPPING（请求方式及传参）
 * @param config
 */
Request.prototype.create = function create(config = {}) {
	this.config = configCopy(configMerge(this.config, config));
}
Request.prototype.request = function(param) {
	const _this = this;
	let n = configCopy(configMerge(param, {}));
	let p = {};
	if (this.reqInterceptors && typeof this.reqInterceptors === 'function') {
		let reqInterceptors = this.reqInterceptors(n);
		if (!reqInterceptors && process.env.NODE_ENV === "development") {
			return false;
		} else if (Object.prototype.toString.call(reqInterceptors) === "[object Promise]") {
			return reqInterceptors;
		}
		p = configCopy(reqInterceptors);
	} else {
		p = configCopy(n);
	}
	let u = handleUrl(p.baseUrl, p.url);
	return new Promise((resolve, reject) => {
		uni.request({
			url: u,
			method: p.method,
			data: p.data ? p.data : {},
			header: p.header,
			dataType: p.dataType,
			responseType: p.responseType,
			timeout: p.timeout,
			async complete(res) {
				if (_this.resInterceptors && typeof _this.resInterceptors === 'function') {
					let resInterceptors = _this.resInterceptors(res);
					if (!resInterceptors) {
						return false;
					} else if (Object.prototype.toString.call(resInterceptors) ===
						"[object Promise]") {
						try {
							let promiseRes = await resInterceptors;
							resolve(promiseRes)
						} catch (error) {
							reject(error)
						}
					} else {
						res = resInterceptors;
					}
				}
				resolve(res);
			}
		});
	})
};
Request.prototype.REQUESTMAPPING = function(method, url, data, header, config, dataType) {
	let o = {
		method, url, data,
		header: header || this.config.header,
		responseType: config || this.config.responseType,
		dataType: dataType || this.config.dataType
	};
	let p = configCopy(configMerge(this.config, o || {}));
	return this.request(p);
};

/**
 * 创建的默认路径 + 接口得到完整路径
 * @param baseUrl
 * @param url
 * @returns {*}
 */
function handleUrl(baseUrl, url) {
	if (!baseUrl) return url;
	if (!url) return baseUrl;
	let handleUrl = '';
	const urlEnd = baseUrl.endsWith('/');
	const urlStart = url.startsWith('/');
	if (urlEnd && urlStart) {
		handleUrl = baseUrl + url.substring(1);
	} else if (urlEnd || urlStart) {
		handleUrl = baseUrl + url;
	} else {
		handleUrl = baseUrl + '/' + url;
	}
	return handleUrl;
};

/**
 * 复制方法
 * @param obj
 * @returns {[]}
 */
function configCopy(obj) {
	let result = Array.isArray(obj) ? [] : {};
	for (let key in obj) {
		if (obj.hasOwnProperty(key)) {
			if (typeof obj[key] === 'object') {
				result[key] = configCopy(obj[key]);
			} else {
				result[key] = obj[key];
			}
		}
	}
	return result;
};

/**
 * 合并方法
 * @param o
 * @param n
 * @returns {*[]}
 */
function configMerge(o, n) {
	let m = configCopy(o);
	if (!n || !Object.keys(n).length) return m;
	for (let key in n) {
		if (key !== 'header') {
			m[key] = n[key];
		} else {
			if (Object.prototype.toString.call(n[key]) === '[object Object]') {
				for (let headerKey in n[key]) {
					m[key][headerKey] = n[key][headerKey];
				}
			}
		}
	}
	return m;
}

export default Request;
